package com.t.bricks.bussiness.service.paperreplytopic.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.t.bricks.bussiness.db.dao.paperreplytopic.PaperReplyTopicDao;
import com.t.bricks.bussiness.db.entity.paperreplytopic.PaperReplyTopic;
import com.t.bricks.bussiness.db.entity.paperreplytopic.base.PaperReplyTopicBase;
import com.t.bricks.bussiness.model.paperreplytopic.ConditionPaperReplyTopic;
import com.t.bricks.bussiness.service.paperreplytopic.PaperReplyTopicService;

import com.t.bricks.model.MsgEmity;
import com.t.bricks.model.OrderInfoList;
import com.t.bricks.model.Page;
import com.t.bricks.utils.function.data.CachePoolUtil;
import com.t.bricks.utils.function.data.ListUtil;
import com.t.bricks.utils.function.file.FileUtil;
import com.t.bricks.utils.modules.web.ModuleUtil;

/**
 * 答卷内具体题目'PaperReplyTopic表'基本业务操作类接口实现
 */
@Service
public class PaperReplyTopicServiceImpl implements PaperReplyTopicService<PaperReplyTopic> {

	@Autowired
	private PaperReplyTopicDao paperReplyTopicDao;

	/**
	 * 是否启用文本缓存
	 */
	private static boolean isUseTxtCache = false;
	
	/**
	 * 缓存文件夹路径
	 */
	private static String sCacheFilePath = new StringBuilder()
		.append(System.getProperty("user.dir").replaceAll("\\\\", "/"))
		.append("/temp/cache/PaperReplyTopic/").toString();
	
	/**
	 * 新增
	 * @param paperReplyTopic 答卷内具体题目 对象实体,注意:跨包访问时可能会是json字符串
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity add(Object paperReplyTopic) {
		MsgEmity me = ModuleUtil.objToEntity(paperReplyTopic, PaperReplyTopic.class);//转换数据,因为如果传递的是String,则可能是进行了跨包访问,要先用Json转换成实体对象
		if (!me.isSuccess()) {
			return me;
		}
		
		PaperReplyTopic paperReplyTopicData = me.getData();
		
		me = ModuleUtil.validDbEntityByAdd(paperReplyTopicData);// 通用的基本数据验证,如果要进行比较复杂的数据验证则可以屏蔽掉此方法自行编写
		if (!me.isSuccess()) {
			return me;
		}
		
		me = ModuleUtil.validDbEntityRepeatByAdd((PaperReplyTopicBase)paperReplyTopicData, paperReplyTopicDao);//查询数据库,验证数据是否有重复,因验证数据重复的方式比较复杂,直接在sql脚本中处理
		if (!me.isSuccess()) {// 在false下,如果返回8028则表示数据库查询异常,否则返回后4位是8026的数据,如xxx8026,从万位起表示从数据库中查询的结果
			String tmp = me.getData().toString();
			tmp = tmp.substring(tmp.length() -4, tmp.length());// 数据一定不小于4位
			return me.setData(tmp);// 发现重复数据后不进行其它业务处理则退出时,必须清理返回数据
		}
		
		synchronized(this) {//由于采用补漏的方式获取节点编号,因此在未保存前存在id冲突的可能
			me = paperReplyTopicDao.newChildId(paperReplyTopicData.getsPid());
			if (!me.isSuccess()) {
				return me;
			}
			
			String vNewId = me.getData();
			paperReplyTopicData.setsId(vNewId);//补充id
			me = ModuleUtil.supplyDbEntityAttrByAdd(paperReplyTopicData, vNewId, null);// 补充数据,如添加id、当前用户、当前时间等
			if (!me.isSuccess()) {
				return me;
			}
	
			//--提交数据保存--//
			me = paperReplyTopicDao.add(paperReplyTopicData);
			if (me.isSuccess()) {
				clearCache(null);//数据出现改动，需要清理缓存
			}
		}
		
		return me;
	}

	/**
	 * 删除
	 * @param iVersion 数据版本号
	 * @param sId 记录编号
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity del(Integer iVersion, String sId) {
		if (null == sId || "".equals(sId.trim())) {
			return new MsgEmity(false, "信息编号参数错误，请刷新重试！", 8001);
		}
		
		if (null == iVersion || iVersion.intValue() < 1) {
			return new MsgEmity(false, "信息版本参数错误，其值应大于0！", 8002);
		}

		MsgEmity me = paperReplyTopicDao.del(sId, iVersion);
		if (me.isSuccess()) {
			clearCache(null);//数据出现改动，需要清理缓存
		}
		
		return me;
	}

	/**
	 * 修改
	 * @param paperReplyTopic 答卷内具体题目 对象实体,注意:跨包访问时可能会是json字符串
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity edit(Object paperReplyTopic) {
		MsgEmity me = ModuleUtil.objToEntity(paperReplyTopic, PaperReplyTopic.class);//转换数据,因为如果传递的是String,则可能是进行了跨包访问,要先用Json转换成实体对象
		if (!me.isSuccess()) {
			return me;
		}
		
		PaperReplyTopic paperReplyTopicData = me.getData();
		
		me = ModuleUtil.validBaseDataByEdit(paperReplyTopicData);// 通用的基本数据验证(编辑),如果要进行比较复杂的数据验证则可以屏蔽掉此方法自行编写
		if (!me.isSuccess()) {
			return me;
		}
		
		me = ModuleUtil.validDbEntityRepeatByEdit((PaperReplyTopicBase)paperReplyTopicData, paperReplyTopicDao);// 查询数据库,验证数据是否有重复,因验证数据重复的方式比较复杂,直接在sql脚本中处理
		if (!me.isSuccess()) {// 在false下,如果返回8028则表示数据库查询异常,否则返回后4位是8026的数据,如xxx8026,从万位起表示从数据库中查询的结果
			String tmp = me.getData().toString();
			tmp = tmp.substring(tmp.length() -4, tmp.length());//数据一定不小于4位
			return me.setData(tmp);// 发现重复数据后不进行其它业务处理则退出时,必须清理返回数据
		}
		
		ModuleUtil.supplyDbEntityAttrByEdit(paperReplyTopicData);// 补充数据
		
		//--提交数据保存--//
		me = paperReplyTopicDao.edit(paperReplyTopicData);
		if (me.isSuccess()) {
			clearCache(null);//数据出现改动，需要清理缓存
		}
		
		return me;
	}

	/**
	 * 根据记录编号取对象
	 * @param sId
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity findById(String sId) {
		if (null == sId || "".equals(sId.trim())) {
			return new MsgEmity(false, "编号不能为空！", 8001);
		}
		
		return paperReplyTopicDao.findById(sId);
	}
	
	/**
	 * 根据字段名取指定记录编号的数据库表中对应字段的值
	 * @param sId 记录编号
	 * @param fieldNames 待取数据的字段名称集合
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity getValueByFieldName(String sId, List<String> fieldNames) {
		if (null == sId || "".equals(sId.trim())) {
			return new MsgEmity(false, "编号不能为空！", 8001);
		}
		
		if (null == fieldNames || fieldNames.size() < 1) {
			return new MsgEmity(false, "待查询字段不能为空！", 8002);
		}
		
		return paperReplyTopicDao.getValueByFieldName(sId, fieldNames);
	}
	
	/**
	 * 根据关键值取对象集合
	 * @param paperReplyTopic 存放查询条件的PaperReplyTopic(答卷内具体题目)对象实体,注意:跨包访问时可能会是json字符串
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity findByKey(Object paperReplyTopic) {
		if (null == paperReplyTopic) {
			return new MsgEmity(false, "条件不能为空！", 8000);
		}
		
		MsgEmity me = ModuleUtil.objToEntity(paperReplyTopic, PaperReplyTopic.class);//转换数据,因为如果传递的是String,则可能是进行了跨包访问,要先用Json转换成实体对象
		if (!me.isSuccess()) {
			return me;
		}
		
		PaperReplyTopic paperReplyTopicData = me.getData();
		
		return paperReplyTopicDao.findByKey(paperReplyTopicData);
	}

	/**
	 * 根据关键值查数量
	 * @Param paperReplyTopic 存放查询条件的PaperReplyTopic对象,注意:跨包访问时可能会是json字符串
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity findCountByKey(Object paperReplyTopic) {
		if (null == paperReplyTopic) {
			return new MsgEmity(false, "条件对象不能为空！", 8000);
		}
		
		MsgEmity me = ModuleUtil.objToEntity(paperReplyTopic, PaperReplyTopic.class);//转换数据,因为如果传递的是String,则可能是进行了跨包访问,要先用Json转换成实体对象
		if (!me.isSuccess()) {
			return me;
		}
		
		PaperReplyTopic paperReplyTopicData = me.getData();
		
		return paperReplyTopicDao.findCountByKey(paperReplyTopicData);
	}
	
	/**
	 * 查询分页
	 * @param page 分页信息对象
	 * @param orders 排序数据集合
	 * @param sLikeStr 全文检索
	 * @param condition 查询条件对象
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity findByPage(Page page, OrderInfoList orders, String sLikeStr,
			ConditionPaperReplyTopic condition) {
		if (null == page) {
			page = new Page(new ArrayList<PaperReplyTopic>());
		}

		return paperReplyTopicDao.findByPage(page, orders, sLikeStr, condition);
	}

	/**
	 * 根据记录编号查询符合分页数据的某条记录
	 * @param sId
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity findByPageRow(String sId) {
		if (null == sId || "".equals(sId.trim())) {
			return new MsgEmity(false, "编号不能为空！", 8001);
		}
		
		return paperReplyTopicDao.findByPageRow(sId);
	}

	/**
	 * 直接调用数据库操作
	 * @param args 参数集合,注意:参数不要使用基本类型
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity callMapping(Object...args) {
		String funName = ModuleUtil.parentMethodName();//待调用的mybits函数名与controller的接口名必须一致
		if (null == funName || "".equals(funName.trim())) {
			return new MsgEmity(false, "调用方法不明！", 8001);
		}
		
		if (null == args) {
			args = new Object[0];
		}
		
		Class<?>[] argsType = new Class<?>[args.length];
		for (int i = 0; i < args.length; i++) {
			argsType[i] = args[i].getClass();
		}
		
		return paperReplyTopicDao.callMapping(funName, argsType, args);
	}

	/**
	 * 创建Excel文件内容
	 * @param orders 排序数据集合
	 * @param sLikeStr 全文检索
	 * @param condition 查询条件对象
	 * @return MsgEmity 返回结构中data为创建的经过压缩的Excel内容,接收端需要进行解压,msg为文件名
	 */
	@Override
	public MsgEmity export(OrderInfoList orders, String sLikeStr, ConditionPaperReplyTopic condition) {
		MsgEmity me = paperReplyTopicDao.findByExport(orders, sLikeStr, condition);//查询数据
		if(!me.isSuccess()) {
			return me;
		}
		
		return ModuleUtil.crateExcel(me.getData(), "答卷内具体题目.xls");//根据Excel的xml模板创建文件内容
	}
	
	/**
	 * 查询答卷内具体题目树信息(给前端返回树形结构权限数据)
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity findByTree() {
		return findByTree(ModuleUtil.currentLoginUserId());//取当前登录用户
	}
	
	/**
	 * 查询字典表树信息(给前端返回树形结构权限数据)
	 * @param sUserId
	 * @return MsgEmity
	 */
	private MsgEmity findByTree(String sUserId) {
		//--从缓存文件读取数据--//
		List<PaperReplyTopic> list = null;
		if (isUseTxtCache) {
			String filePath = new StringBuilder(sCacheFilePath)
				.append(sUserId).append("_PaperReplyTopicTree.txt").toString();
			list = CachePoolUtil.readCacheFile(PaperReplyTopic.class, filePath);//读取预存储的缓存文件
		}
		
		boolean isReadDb = false;
		if (null == list || list.size() < 1) {
			MsgEmity me = paperReplyTopicDao.findByTree(sUserId);//读库
			if (!me.isSuccess()) {
				return me;
			}
			
			list = me.getData();
			isReadDb = true;
			
			me = ListUtil.createTree(list, "0000", "sId", "sPid", "childs");//通用方法构造树形结构
			if (!me.isSuccess()) {
				return me.setData(3100 + (Integer)me.getData());
			}
			
			list = me.getData();
		}
		
		if (null == list || list.size() < 1) {
			return new MsgEmity(false, "获取树形数据信息为空！", 8001);
		}
		
		if (isReadDb && isUseTxtCache) {//重新读取了数据库并且使用Txt缓存
			CachePoolUtil.createCacheFile(list, new StringBuilder(sCacheFilePath)
						.append(sUserId).append("_PaperReplyTopicTree.txt").toString());//写入文件，以便下次不用读库
		}
		
		return MsgEmity.success(list, "树形数据查询成功");
	}
	
	/**
	 * 清理指定用户的缓存
	 * @param sUser 用户编号
	 * @return MsgEmity
	 */
	@Override
	public MsgEmity clearCache(String sUser) {
		if (!isUseTxtCache) {
			return MsgEmity.err(8001, "没有启用缓存！");
		}
		
		StringBuilder filePath = new StringBuilder(sCacheFilePath);
		
		if (null == sUser || "".equals(sUser.trim())) {
			if (FileUtil.delDir(filePath.toString())) {
				rebuildCheach(true);
				return MsgEmity.success(8999, "删除所有用户的'答卷内具体题目'缓存成功！");
			}
			
			if (new File(filePath.toString()).exists()) {
				return MsgEmity.err(8002, "试图删除所有用户的'答卷内具体题目'缓存失败！");
			}
			
			rebuildCheach(true);
			
			return MsgEmity.success(8999, "请求删除所有用户的'答卷内具体题目'缓存成功！");
		}
		
		filePath.append(sUser.trim()).append("_PaperReplyTopicTree.txt").toString();
		if (FileUtil.delFile(filePath.toString())) {
			rebuildCheach(true);
			return MsgEmity.success(8999, "请求删除用户的'答卷内具体题目'缓存成功！");
		}
		
		if (new File(filePath.toString()).exists()) {
			return MsgEmity.err(8003, "试图删除用户的'答卷内具体题目'缓存失败！");
		}
		
		rebuildCheach(true);
		
		return MsgEmity.success(8999, "请求删除用户的'答卷内具体题目'缓存成功！");
	}
	
	/**
	 * 重建缓存
	 * @param newThread
	 */
	private void rebuildCheach(boolean newThread) {
		String currentLoginUserId = ModuleUtil.currentLoginUserId();//取当前登录用户
		
		/**
		 * 多线程方式重新构造缓存数据
		 */
		Thread thread = new Thread() {
			@Override
			public void run() {
				findByTree(currentLoginUserId);
			}
		};
		
		if (newThread) {
			thread.start();
			return;
		}
		
		thread.run();//非多线程操作
	}

	/**
	 * 修改状态
	 * @param sId 编号
	 * @param iState 状态值
	 * @param iVersion 记录版本号
	 * @param sMemo 备注
	 * @return MsgEmity 返回执行情况
	 */
	@Override
	public MsgEmity changeState(String sId, Integer iState, Integer iVersion, String sMemo) {
		if (null == sId || "".equals(sId.trim())) {
			return new MsgEmity(false, "编号不能为空！", 8001);
		}
		
		if (null == iState) {
			return new MsgEmity(false, "状态值不能为空！", 8002);
		}
		
		if (null == iVersion || iVersion.intValue() < 1) {
			return new MsgEmity(false, "版本号不该小于1！", 8003);
		}
		
		return paperReplyTopicDao.changeState(sId, iState, iVersion, sMemo);
	}
	
	//----------------------------- 自动生成代码结束 -----------------------------//

}
